package com.shelpe.services.lexicon.service.price;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;

import com.shelpe.services.lexicon.entity.AdgroupRecord;
import com.shelpe.services.lexicon.entity.KeywordRecommend;
import com.shelpe.services.lexicon.entity.WordInsightMetric;
import com.shelpe.services.lexicon.entity.metrics.InsightMetrics;
import com.shelpe.services.lexicon.properties.AutoDriveParams;
import com.shelpe.services.lexicon.repository.mongo.AdgroupRecordRepository;
import com.shelpe.services.lexicon.utils.PriceUtils;

import lombok.extern.slf4j.Slf4j;

@Service
@Order(1)
@Slf4j
public class PriceScoreRecommendPriceRule implements WordPricingRule<KeywordRecommend, InsightMetrics, RecommendPriceRuleContext> {
	
	@Autowired
	private AutoDriveParams params;
	@Autowired
	private AdgroupRecordRepository adgroupRecordRepository;
	@Autowired
	private CosineSimilarAlgorithmRule similarRule;

	@Override
	public int score(KeywordRecommend word, InsightMetrics metric, RecommendPriceRuleContext context) {
		int score = PriceUtils.weight(word, context.getMode().getPriceWeight());
		
		context.compareMaxScore(score);
		context.compareMinScore(score);
		word.setScore(score);
		return word.getScore();
	}

	@Override
	public int price(KeywordRecommend word, InsightMetrics metric, RecommendPriceRuleContext context) {
		float defaultPrice = metric.getCpc().floatValue() / 100;
		if(defaultPrice == 0 && word.getMetric() != null && word.getMetric().getAveragePrice() != null){//
			defaultPrice = word.getMetric().getAveragePrice().floatValue();
		}
		if(context.getDefaultPrice() > 0){
			defaultPrice = context.getDefaultPrice();
		}
		
		float price = defaultPrice;
		if(price > 0){
			float scoreScope = context.getMaxScore() - context.getMinScore();
			scoreScope = scoreScope / 100;
			if(scoreScope > 0){
				float ratioScope = context.getMode().getMaxPriceRatio() - context.getMode().getMinPriceRatio();
				ratioScope = ratioScope / 100;
				float scope = word.getScore() - context.getMinScore();
				scope = scope / 100;
				
				float ratio = ((float) context.getMode().getMinPriceRatio()) / 100;
				ratio = ratio + (ratioScope / scoreScope) * scope;
				price = price * ratio;
				if(price == 0){
					price = defaultPrice;
				}
				
				price = price * 100;
			}else{
				price = defaultPrice * 100;
			}
			
			if(price < params.getMinPrice()){
				price = params.getMinPrice();
			}
			if(context.getMaxtPrice() > 0 && price > context.getMaxtPrice()){
				price = context.getMaxtPrice();
			}
		}
		word.setPrice((int) (price));
		return word.getPrice();
	}

	@Override
	public int performace(KeywordRecommend word, InsightMetrics metric, RecommendPriceRuleContext context) {
		int performance = -1;
		float price = metric.getCpc().floatValue();
		if(word.getInsight() != null){
			if(price > 0){
				if(word.getInsight().getImpression() > 0){
					performance = (int) ((metric.getImpression() * 100) / (price * metric.getImpression()));
				}
			}
		}
		
		if(performance > 0){
			context.compareMaxPerformance(performance);
		}
		word.setPerformance(performance);
		
		return word.getPerformance();
	}

	@Override
	public int pqr(KeywordRecommend word, InsightMetrics metric, RecommendPriceRuleContext context) {
		double pqr = 0;
		
		if(word.getPerformance() == -1){
			
			pqr = ((double) metric.getImpression()) / 10000;
			
			if(pqr > 1){
				pqr = 1;
			}
		}else if(context.getMaxPerformance() > 0){
			if(word.getPerformance() > 0){
				pqr = ((double) word.getPerformance()) / context.getMaxPerformance();
			}
		}
		
		if(pqr > 0){
			pqr = Math.pow(pqr, 1d/3d);
			word.setPqr((int) (pqr * 100));
		}
		
		return word.getPqr();
	}

	@Override
	public int similarity(KeywordRecommend word, InsightMetrics metric, RecommendPriceRuleContext context) {
		
		double catSim = 0;
		double prodSim = 0;
		
		AdgroupRecord record = this.adgroupRecordRepository.findOne(word.getAdgroupRecordID());
		WordInsightMetric catMetric = context.getCategoryInsight();
		if(catMetric != null){
			double cat = catMetric.getMetric().getImpression() + 1;
			double prod = metric.getImpression() + 1;
			
			catSim = (cat / prod) * (1d - 1d / Math.sqrt(prod));
			if(catSim > 1){
				catSim = 1;
			}
		}
		word.setCategorySimilarity((int) (catSim * 100));
		
		if(record.getSource() != null && record.getSource().getItemName() != null){
			prodSim = similarRule.compare(word.getWord(), record.getSource().getItemName());
		}
		word.setProductSimilarity((int) (prodSim * 100));
		
		int similarity = (int) (Math.pow(Math.pow(prodSim, 0.5) * catSim, 0.5) * 100);
		word.setSimilarity(similarity);
		
		log.debug("similarity {}: {}", word.getSimilarity(), word.getWord());
		
		return similarity;
	}
	
	

}
